Skip to content

feat: Adaptive Volatility-Aware Recurring Deposit (Smart DCA) Engine - #386

Open
dotunv wants to merge 1 commit into
Neurowealth:mainfrom
dotunv:feat/311-smart-dca-engine
Open

feat: Adaptive Volatility-Aware Recurring Deposit (Smart DCA) Engine#386
dotunv wants to merge 1 commit into
Neurowealth:mainfrom
dotunv:feat/311-smart-dca-engine

Conversation

@dotunv

@dotunv dotunv commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Upgrades recurring deposits from a fixed-amount cron job into an adaptive, portfolio-aware investment engine with transparent preview and honest failure semantics.

Closes #311


What's New

Pure Policy Module (src/deposits/smartDcaPolicy.ts)

  • Zero-I/O, zero side effects — fully unit-testable with fixture data
  • Volatility regime classification: HIGH (cheap → buy more), NORMAL, LOW (expensive → buy less) computed from trailing APY observations
  • Bounded regime scaling: configurable floor/ceiling fractions prevent extreme contributions
  • Drawdown pause/double: skips (or doubles, per config) when portfolio drawdown exceeds threshold — reuses the same pattern as alertEvaluator.computeDrawdownPercent
  • Multi-protocol allocation: splits contribution across protocols by weight map
  • Catch-up state machine: RETRY (retry same run), SKIP (advance), ACCUMULATE (accumulate missed runs, capped at 10)
  • Auto-pause backoff: after 5 consecutive failures, plan auto-pauses with user-visible reason
  • FIXED plans: byte-for-byte identical to legacy behavior — zero change for existing users

Preview Endpoint (GET /api/v1/deposit/recurring/preview)

  • Deterministic simulation of the next N runs under the plan's policy
  • Shows regime assumptions, drawdown state, allocation math
  • Explicitly labeled as simulation with disclaimer

Run Ledger (GET /api/v1/deposit/recurring/:id/runs)

  • Per-run record: baseline amount, applied amount, regime snapshot, reasoning
  • Paginated, owner-scoped

Schema Extensions

  • RecurringDepositPlan: policy, catchUpMode, pauseOnDrawdownPct, doubleOnDrawdown, accumulatedRuns, consecutiveFailures, autoPauseReason, allocationMap
  • New RecurringDepositRun model for the per-run audit trail
  • New enums: ContributionPolicy, CatchUpMode, RecurringDepositRunStatus

Files Changed

File Description
prisma/schema.prisma Schema extensions + RecurringDepositRun model
prisma/migrations/20260828160000_smart_dca_engine/ SQL migration
src/deposits/smartDcaPolicy.ts Pure policy engine (530 lines)
src/deposits/preview.ts Preview/simulation service (179 lines)
src/jobs/recurringDeposits.ts Scheduler with adaptive logic, run ledger, auto-pause
src/routes/recurring-deposits.ts New endpoints: /preview, /:id/runs
src/validators/recurring-deposit-validators.ts Extended validation schemas
tests/unit/deposits/smartDcaPolicy.test.ts 46 unit tests

Acceptance Criteria Checklist

  • FIXED plans behave byte-for-byte like today (backward-compatible regression tests)
  • ADAPTIVE policy scales contributions by a documented, bounded, unit-tested regime model
  • No-history plan falls back to baseline with a visible flag
  • Pause-on-drawdown skips-and-reschedules (or doubles, per config) — never silently drops
  • Catch-up is capped (max 10), documented, and tested
  • Per-run ledger records baseline vs. applied amount, regime snapshot, and reasoning
  • Preview endpoint simulates N future runs deterministically and labels itself as simulation
  • Repeated failures auto-pause with alert + user-visible reason
  • Multi-protocol allocation validated and fail-closed
  • Typecheck passes, all 1242 unit tests green (82 suites)

Design Decisions

  1. FIXED backward compatibility: The policy module is a no-op for FIXED plans — same amount, no regime check, no drawdown pause. Existing plans are completely unaffected.

  2. Regime classification: Uses the "latest value relative to its trailing range" approach — simple, documented, and auditable. Not a forecast. The regime snapshot is stored with every run for full auditability.

  3. Drawdown detection: Reuses the same peak-tracking pattern from alertRules.ts (computeDrawdownPercent + rollingPeak), so the platform has one consistent definition of drawdown.

  4. Auto-pause backoff: After 5 consecutive failures, the plan auto-pauses with a user-visible reason. This mirrors the retriable-failure philosophy of referralPayout.ts and fiatReconciliation.ts.

  5. Run ledger vs. AgentLog: The run ledger is the policy audit trail (what the engine decided and why). AgentLog remains the deposit audit trail (what happened on-chain). Two separate concerns, two separate records.

Testing

✅ Typecheck: 0 errors
✅ Unit tests: 1242 passed, 0 failed (82 suites)
✅ New tests: 46 passed — regime, drawdown, scaling, allocation, catch-up, validation
✅ Existing tests: all pass, zero regressions

🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com

…eurowealth#311)

Upgrade recurring deposits from fixed-amount cron to an adaptive,
portfolio-aware investment engine with transparent preview and honest
failure semantics.

Schema:
- Extend RecurringDepositPlan with: policy (FIXED/ADAPTIVE),
  catchUpMode, pauseOnDrawdownPct, doubleOnDrawdown, accumulatedRuns,
  consecutiveFailures, autoPauseReason, allocationMap
- Add RecurringDepositRun model for per-run ledger (baseline vs applied
  amount, regime snapshot, reasoning, allocation legs)

Pure Policy Module (src/deposits/smartDcaPolicy.ts):
- Zero-I/O, unit-testable contribution sizing
- Volatility regime classification (HIGH/NORMAL/LOW) from trailing data
- Bounded regime scaling with floor/ceiling (configurable fractions)
- Drawdown pause/double logic (reuses alertEvaluator pattern)
- Multi-protocol allocation splitting
- Catch-up state machine (RETRY/SKIP/ACCUMULATE)
- Auto-pause after consecutive failures
- FIXED plans: byte-for-byte identical to legacy (backward compatible)

Preview Service (src/deposits/preview.ts):
- Deterministic simulation of next N runs under plan policy
- Explicitly labeled as simulation, not a guarantee
- Shows regime assumptions, drawdown state, allocation math

Scheduler (src/jobs/recurringDeposits.ts):
- Resolves effective strategy config (own vs. followed)
- Loads regime + drawdown data for ADAPTIVE plans
- Creates run ledger row for every execution attempt
- Auto-pause with user-visible reason after consecutive failures
- RESET consecutiveFailures on success

Validators: extended with policy, catchUpMode, allocationMap, preview/run
query schemas.

Routes: POST create + PATCH update support new fields; GET /preview
(registered before /:id); GET /:id/runs (paginated run ledger).

Closes Neurowealth#311

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Adaptive Volatility-Aware Recurring Deposit (Smart DCA) Engine

1 participant